#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int N = 5001;
int n, m, s, t, cnt = 1, ans = 0, cost = 0;
int heads[N], pre[N], dis[N], f[N], last[N];
bool vis[N];

struct Edge {
	int v, nxt, flow, c;
} e[100002];
inline void add(int u, int v, int f, int cos) {
	e[++cnt].flow = f, e[cnt].nxt = heads[u], e[cnt].c = cos, e[cnt].v = v, heads[u] = cnt;
	e[++cnt].flow = 0, e[cnt].nxt = heads[v], e[cnt].v = u, e[cnt].c = -cos, heads[v] = cnt;
}

bool spfa() {
	queue< int > q;
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	memset(f, 0x3f, sizeof(f));
	q.push(s);
	vis[s] = true, dis[s] = 0, pre[t] = -1;
	while (!q.empty()) {
		int x = q.front();
		q.pop();
		vis[x] = false;
		for (int i = heads[x]; i; i = e[i].nxt) {
			if (e[i].flow > 0 && dis[e[i].v] > dis[x] + e[i].c) {
				dis[e[i].v] = dis[x] + e[i].c;
				pre[e[i].v] = x;
				last[e[i].v] = i;
				f[e[i].v] = min(f[x], e[i].flow);
				if (!vis[e[i].v]) {
					q.push(e[i].v);
					vis[e[i].v] = true;
				}
			}
		}
	}
	return pre[t] != -1;
}

void MCMF() {
	while (spfa()) {
		int cur = t;
		ans += f[t];
		cost += f[t] * dis[t];
		while (cur != s) {
			e[last[cur]].flow -= f[t];
			e[last[cur] ^ 1].flow += f[t];
			cur = pre[cur];
		}
	}
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
	freopen("testdata.in", "r", stdin);
	freopen("testdata.out", "w", stdout);
#endif
#ifndef LOCAL
	freopen("MCMF.in", "r", stdin);
	freopen("MCMF.out", "w", stdout);
#endif
#endif
	scanf("%d%d%d%d", &n, &m, &s, &t);
	int t1, t2, t3, t4;
	for (int i = 1; i <= m; ++i) {
		scanf("%d%d%d%d", &t1, &t2, &t3, &t4);
		add(t1, t2, t3, t4);
	}
	MCMF();
	printf("%d %d", ans, cost);
	return 0;
}